#ifndef _VPI_H_
#define _VPI_H_

/*
 * VPI Datatype
 */
#define VPI_SUCCESS		(0)
#define VPI_EFAIL 		(-1)
#define VPI_EPARAMS 	(-2) // invalid parameters
#define VPI_EFORMAT 	(-3) // package format error
#define VPI_ECHECKSUM 	(-4) // checksum error
#define VPI_ERESPCMD 	(-5) // response cmd error
#define VPI_EMEM 		(-6) // memory error
#define VPI_ESPACE 		(-7) // buff space is not enough

#define VPI_INVALID_CMD (0x00)


typedef enum protocol_role
{
	ROLE_DEV = 0,
	ROLE_PC,
	ROLE_SERVER,
	ROLE_MAX
}eproto_role;

typedef struct protocol_msg
{
	unsigned int cmd;
	unsigned int length; /* protocol content data-structute length */
	void *content;
}sproto_msg;

/** protocol package build and parse function handle */
typedef int (*build_func)(eproto_role role,sproto_msg *pmsg, unsigned char *sendbuff,int *len);
typedef int (*parse_func)(eproto_role role,sproto_msg *pmsg, unsigned char *recvbuff, int len);

typedef struct protocol_header
{
	int type;
	char name[32];
	char version[32];
	int length; /* protocol uniform structure length,used for malloc content space */
	build_func build;
	parse_func parse;
}sproto_header;

typedef struct protocol_package
{
	eproto_role role;
	sproto_header header;
	sproto_msg 	  msg;
}sproto_package;

typedef const sproto_header * VPI_HRDESC;
typedef sproto_package* VPI_HANDLE;

/******************* Function Declarations ********************/

void vpi_print_pack_helper(const unsigned char *buff, unsigned int len);
void vpi_print_package(const unsigned char *buff, unsigned int len);
int  vpi_calc_checksum(const unsigned char *buff, int len);

/**
 * initialize protocol handle
 *
 * malloc a vpi handle and specific protocol content memory to use.
 * @param[in] proto the specific protocol header 
 * @param[in] role the user role
 * @return vpi handle used in vpi_build_package and vpi_parse_package api.
 */
VPI_HANDLE vpi_handle_init(VPI_HRDESC proto, int role);

/**
 * deinitialize protocol handle
 *
 * free memory malloced in vpi_handle_init api.
 * @param[in] handle the vpi handle got in vpi_handle_init. 
 */
void vpi_handle_exit(VPI_HANDLE handle);

/**
 * build protocol package uniform interface
 *
 * build protocol package to send,caller need to fill the protocol cmd in
 * handle->msg.cmd and fill the protocol content in handle->msg.content.
 * @param[in] handle vpi handle returned by vpi_handle_init
 * @param[in,out] sendbuff buff to store the build-package
 * @param[in] len sendbuff available length
 * @return the package valid length in sendbuff if success, or VPI error
 * code(<0).
 */
int vpi_build_package(VPI_HANDLE handle,unsigned char *sendbuff, int len);

/**
 * parse protocol package uniform interface
 *
 * parse protocol package from recvbuff,and fill the protocol content in
 * handle->msg.content, fill protocol cmd in handle->msg.cmd.
 * @param[in,out] handle vpi handle returned by vpi_handle_init
 * @param[in] recvbuff the protocol raw package that need to parsed
 * @param[in] len recvbuff raw package length
 * @return VPI_SUCCESS if success,or vpi errorcode(<0).
 */
int vpi_parse_package(VPI_HANDLE handle,unsigned char *recvbuff, int len);

#endif

